import React from 'react'
import { combineReducers } from 'redux'

import createApp from 'index'
import system from 'modules/system'
import createHandlersMiddleware from 'middlewares/createHandlersMiddleware'

const handlersMiddleware = createHandlersMiddleware([])
const setup = () => {
  const rootId = 'root'
  const reducer = combineReducers({ system })
  const counterReducer = (state = 0, action) => {
    switch (action.type) {
      case 'INCREMENT':
        return state + 1
      case 'DECREMENT':
        return state - 1
      default:
        return state
    }
  }

  document.body.innerHTML = `<div id='${rootId}'></div>`

  return {
    rootId,
    rootElement: document.getElementById(rootId),
    reducer,
    counterReducer,
  }
}

it('createApp with reducer object', () => {
  const { rootId, rootElement, reducer } = setup()
  const callbackMock = jest.fn()

  createApp()
    .reducer({ reducer })
    .view(() => <p>Hello World</p>)
    .run(`#${rootId}`, callbackMock)

  expect(callbackMock).toBeCalled()
  expect(rootElement.innerHTML.includes('Hello World')).toBe(true)
  expect(rootElement.innerHTML).toMatchSnapshot()
})

it('createApp without calling `reducer` method', () => {
  const { rootId, rootElement } = setup()
  const callbackMock = jest.fn()

  createApp().view(() => <p>Hello World</p>).run(`#${rootId}`, callbackMock)

  expect(callbackMock).toBeCalled()
  expect(rootElement.innerHTML.includes('Hello World')).toBe(true)
  expect(rootElement.innerHTML).toMatchSnapshot()
})

it('createApp with calling reducer function', () => {
  const { rootElement, counterReducer } = setup()
  const callbackMock = jest.fn()

  createApp()
    .reducer(counterReducer)
    .view(() => <p>Hello World</p>)
    .run(rootElement, callbackMock)

  expect(callbackMock).toBeCalled()
  expect(rootElement.innerHTML.includes('Hello World')).toBe(true)
  expect(rootElement.innerHTML).toMatchSnapshot()
})

it('middleware', () => {
  const { rootElement, reducer } = setup()
  const callbackMock = jest.fn()

  const app = createApp()
    .reducer({ reducer })
    .middleware([handlersMiddleware])
    .view(() => <p>Hello World</p>)
    .run(rootElement, callbackMock)
  const store = app.getStore()

  expect(store.asyncReducers).toMatchSnapshot()
})

it('createHistory', () => {
  const { rootElement, reducer } = setup()
  const callbackMock = jest.fn()

  const app = createApp()
    .reducer({ reducer })
    .middleware([handlersMiddleware])
    .view(() => <p>Hello World</p>)
    .createHistory({ basename: '/arc-ui' })
    .run(rootElement, callbackMock)
  const store = app.getStore()

  expect(store.asyncReducers).toMatchSnapshot()
})

it('injectL10nProvider', () => {
  const { rootElement, reducer } = setup()
  const callbackMock = jest.fn()

  const app = createApp()
    .reducer({ reducer })
    .view(() => <p>Hello World</p>)
    .injectL10nProvider(({ children }) => <div>{children}</div>)
    .run(rootElement, callbackMock)
  const store = app.getStore()

  expect(store.asyncReducers).toMatchSnapshot()
})

it('getStore', () => {
  const { rootElement, reducer } = setup()
  const callbackMock = jest.fn()

  const app = createApp()
    .reducer({ reducer })
    .view(() => <p>Hello World</p>)
    .run(rootElement, callbackMock)
  const store = app.getStore()

  expect(store.asyncReducers).toMatchSnapshot()
})
